From c298e49c5a828a5eeaae16d23dd4785d999b2b3e Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Tue, 19 Feb 2008 09:22:25 -0700 Subject: [PATCH] [IA64] Handle long vhpt format for ttag and thash. Improve tak emulation. Signed-off-by: Tristan Gingold --- xen/arch/ia64/vmx/vmmu.c | 149 ++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 64 deletions(-) diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index ee03f6fc63..8097533403 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -467,16 +467,19 @@ u64 vmx_vcpu_thash(VCPU *vcpu, u64 vadr) ia64_rr vrr; u64 pval; u64 vhpt_offset; + u64 mask; + vpta.val = vmx_vcpu_get_pta(vcpu); vcpu_get_rr(vcpu, vadr, &vrr.rrval); - if(vpta.vf){ - pval = ia64_call_vsa(PAL_VPS_THASH, vadr, vrr.rrval, - vpta.val, 0, 0, 0, 0); - pval = vpta.val & ~0xffff; - }else{ - vhpt_offset=((vadr>>vrr.ps)<<3)&((1UL<<(vpta.size))-1); + mask = (1UL << vpta.size) - 1; + if (vpta.vf) { + vadr = (vadr & 0x1fffffffffffffffUL) >> vrr.ps; + vhpt_offset = vadr ^ vrr.rid; + pval = (vpta.val & ~0x7fffUL) + ((vhpt_offset << 5) & mask); + } else { + vhpt_offset=((vadr >> vrr.ps) << 3) & mask; pval = (vadr & VRN_MASK) | - (vpta.val<<3>>(vpta.size+3)<<(vpta.size))| + (vpta.val << 3 >> (vpta.size + 3) << vpta.size) | vhpt_offset; } return pval; @@ -488,10 +491,13 @@ u64 vmx_vcpu_ttag(VCPU *vcpu, u64 vadr) ia64_rr vrr; PTA vpta; u64 pval; + u64 rid; vpta.val = vmx_vcpu_get_pta(vcpu); vcpu_get_rr(vcpu, vadr, &vrr.rrval); if(vpta.vf){ - pval = ia64_call_vsa(PAL_VPS_TTAG, vadr, vrr.rrval, 0, 0, 0, 0, 0); + vadr = (vadr & 0x1fffffffffffffffUL) >> vrr.ps; + rid = vrr.rid; + pval = vadr ^ (rid << 39); }else{ pval = 1; } @@ -507,83 +513,85 @@ IA64FAULT vmx_vcpu_tpa(VCPU *vcpu, u64 vadr, u64 *padr) REGS *regs; u64 vhpt_adr, madr; IA64_PSR vpsr; - regs=vcpu_regs(vcpu); - pt_isr.val=VMX(vcpu,cr_isr); - visr.val=0; - visr.ei=pt_isr.ei; - visr.ir=pt_isr.ir; + + regs = vcpu_regs(vcpu); + pt_isr.val = VMX(vcpu, cr_isr); + visr.val = 0; + visr.ei = pt_isr.ei; + visr.ir = pt_isr.ir; vpsr.val = VCPU(vcpu, vpsr); - visr.na=1; + visr.na = 1; + + /* First look in VTLB. */ data = vtlb_lookup(vcpu, vadr, DSIDE_TLB); - if(data){ - if(data->p==0){ + if (data) { + if (data->p == 0) { vcpu_set_isr(vcpu,visr.val); data_page_not_present(vcpu, vadr); return IA64_FAULT; - }else if(data->ma == VA_MATTR_NATPAGE){ + } else if (data->ma == VA_MATTR_NATPAGE) { vcpu_set_isr(vcpu, visr.val); dnat_page_consumption(vcpu, vadr); return IA64_FAULT; - }else{ + } else { *padr = ((data->ppn >> (data->ps - 12)) << data->ps) | (vadr & (PSIZE(data->ps) - 1)); return IA64_NO_FAULT; } } + + /* Look in mVHPT. */ data = vhpt_lookup(vadr); - if(data){ - if(data->p==0){ + if (data) { + if (data->p == 0) { vcpu_set_isr(vcpu,visr.val); data_page_not_present(vcpu, vadr); return IA64_FAULT; - }else if(data->ma == VA_MATTR_NATPAGE){ + } else if (data->ma == VA_MATTR_NATPAGE) { vcpu_set_isr(vcpu, visr.val); dnat_page_consumption(vcpu, vadr); return IA64_FAULT; - }else{ + } else { madr = (data->ppn >> (data->ps - 12) << data->ps) | (vadr & (PSIZE(data->ps) - 1)); *padr = __mpa_to_gpa(madr); return IA64_NO_FAULT; } } - else{ - if(!vhpt_enabled(vcpu, vadr, NA_REF)){ - if(vpsr.ic){ - vcpu_set_isr(vcpu, visr.val); - alt_dtlb(vcpu, vadr); - return IA64_FAULT; - } - else{ - nested_dtlb(vcpu); - return IA64_FAULT; - } + + /* If VHPT is not enabled, inject fault. */ + if (!vhpt_enabled(vcpu, vadr, NA_REF)) { + if (vpsr.ic) { + vcpu_set_isr(vcpu, visr.val); + alt_dtlb(vcpu, vadr); + return IA64_FAULT; + } else { + nested_dtlb(vcpu); + return IA64_FAULT; } - else{ - vhpt_adr = vmx_vcpu_thash(vcpu, vadr); - data = vtlb_lookup(vcpu, vhpt_adr, DSIDE_TLB); - if(data){ - if(vpsr.ic){ - vcpu_set_isr(vcpu, visr.val); - dtlb_fault(vcpu, vadr); - return IA64_FAULT; - } - else{ - nested_dtlb(vcpu); - return IA64_FAULT; - } - } - else{ - if(vpsr.ic){ - vcpu_set_isr(vcpu, visr.val); - dvhpt_fault(vcpu, vadr); - return IA64_FAULT; - } - else{ - nested_dtlb(vcpu); - return IA64_FAULT; - } - } + } + + /* Get gVHPT entry. */ + vhpt_adr = vmx_vcpu_thash(vcpu, vadr); + data = vtlb_lookup(vcpu, vhpt_adr, DSIDE_TLB); + if (data) { + /* FIXME: we should read gadr from the entry! */ + if (vpsr.ic) { + vcpu_set_isr(vcpu, visr.val); + dtlb_fault(vcpu, vadr); + return IA64_FAULT; + } else { + nested_dtlb(vcpu); + return IA64_FAULT; + } + } else { + if (vpsr.ic) { + vcpu_set_isr(vcpu, visr.val); + dvhpt_fault(vcpu, vadr); + return IA64_FAULT; + } else { + nested_dtlb(vcpu); + return IA64_FAULT; } } } @@ -598,12 +606,25 @@ u64 vmx_vcpu_tak(VCPU *vcpu, u64 vadr) return key; } - /* FIXME: if psr.dt is set, look in the guest VHPT. */ data = vtlb_lookup(vcpu, vadr, DSIDE_TLB); - if (!data || !data->p) - key = 1; - else - key = data->key << 8; + if (data) { + if (data->p) + return data->key << 8; + else + return 1; + } + + data = vhpt_lookup(vadr); + if (data) { + if (data->p) + return data->key << 8; /* FIXME: possible mangling/masking. */ + else + return 1; + } + + if (!vhpt_enabled(vcpu, vadr, NA_REF)) + return 1; - return key; + /* FIXME: look in the guest VHPT. */ + return 1; } -- 2.30.2